/*
 * ======== Standard MSP430 includes ========
 */
#include <msp430.h>

/*
 * ======== Grace related includes ========
 */
#include <ti/mcu/msp430/csl/CSL.h>

/*
 * Defines for the morse timings
 */
#define DIT				200
#define DAH				(3*DIT)
#define PAUSE_SYM		DIT
#define PAUSE_LETTER	DAH
#define PAUSE_WORD		(7 * DIT)

// define bool
#define TRUE	0
#define FALSE	1

// define the morse alphabet (static puts the alphabet to the flash instead of ram)
static const char* alphabet[] = { ".-", // A
		"-...", // B
		"-.-.", // C
		"-..", // D
		".", // E
		"..-.", // F
		"--.", // G
		"....", // H
		"..", // I
		".---", // J
		"-.-", // K
		".-..", // L
		"--", // M
		"-.", // N
		"---", // O
		".--.", // P
		"--.-", // Q
		".-.", // R
		"...", // S
		"-", // T
		"..-", // U
		"...-", // V
		".--", // W
		"-..-", // X
		"-.--", // Y
		"--.." // Z
		};

// define the initial word to morse
#define WORD 	"SOS"

// output buffer
#define OUT_BUFF_SIZE 256
char outBuffer[256] = { 'x' };
unsigned int currOutPos = 0;
unsigned int currReadPos = 0;

// global time
unsigned int gSysTime = 0;
unsigned int gWaitTime = 0;
unsigned int gCurrTime = 0;

/*
 * Put a word into the buffer
 * word: The word to put into the buffer
 */
void put(char* word);

/*
 * Start atomic process. Interrupts disabled
 */
void BEGIN_ATOMIC(void);

/*
 * End atomic process Interrupts enabled
 */
void END_ATOMIC(void);

/*
 *  ======== main ========
 */
int main(int argc, char *argv[]) {
	CSL_init(); // Activate Grace-generated configuration

	put(WORD);

	return (0);
}

void put(char* word) {
	char* currLetter = word;

	// iterate through the word
	while (*currLetter != '\0') {

		// calculate the index of this letter
		unsigned int letter = ((int) *currLetter) % 65;

		const char* morseLetter;
		if (letter < 26) {
			morseLetter = alphabet[letter];
		} else {
			// x for pause between words
			morseLetter = "x";
		}

		while (*morseLetter != '\0') {
			if (currOutPos < OUT_BUFF_SIZE) {
				outBuffer[currOutPos] = *morseLetter;
				currOutPos++;

				// pause between symbols
				outBuffer[currOutPos] = 's';
				currOutPos++;
			}
			morseLetter++;
		}

		// pause between letters
		outBuffer[(currOutPos-1)] = 'p';

		currLetter++;
	}

	outBuffer[(currOutPos-1)] = 'x';
	outBuffer[currOutPos] = '\0';
}

/*
 * Method for timer interrupt
 */
void timerInterrupt() {
	BEGIN_ATOMIC();

	// increment by 100 ms
	gSysTime += 100;

	if (gWaitTime >= gCurrTime) {
		gCurrTime += 100;
	} else {
		gWaitTime = 0;
		gCurrTime = 0;
		char currSym = outBuffer[currReadPos];

		if (currSym != '\0') {
			if (currSym == '.') {
				gWaitTime = DIT;
				P1OUT ^= BIT0;
			} else if (currSym == '-') {
				gWaitTime = DAH;
				P1OUT ^= BIT0;
			} else if (currSym == 'x') {
				gWaitTime = PAUSE_WORD;
				P1OUT ^= BIT0;
			} else if (currSym == 'p') {
				gWaitTime = PAUSE_LETTER;
				P1OUT ^= BIT0;
			} else if (currSym == 's') {
				gWaitTime = PAUSE_SYM;
				P1OUT ^= BIT0;
			}
			currReadPos++;
		} else {
			// turn off and stay off
			P1OUT &= !BIT0;
		}
	}

	END_ATOMIC();
}

void BEGIN_ATOMIC(void){
	// disable global interrupts
	__disable_interrupt();
}


void END_ATOMIC(void){
	// enable global interrupts
	__enable_interrupt();
}
